using CliWrap;
using CliWrap.Buffered;
using Ke.Bee.Shared.Abstractions;
using Ke.Bee.Shared.Models.Multimedias;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Ke.Bee.Shared.Impl;

/// <summary>
/// FFmpeg 音频提取器
/// </summary>
public class FFmpegAudioExtractor : IAudioExtractor
{
    private readonly FFmpegOptions _ffmpegOptions;
    private readonly ILogger<FFmpegAudioExtractor> _logger;

    public FFmpegAudioExtractor(IOptions<FFmpegOptions> ffmpegOptions, ILogger<FFmpegAudioExtractor> logger)
    {
        if (!File.Exists(ffmpegOptions.Value.FFmpegPath))
        {
            throw new FileNotFoundException(ffmpegOptions.Value.FFmpegPath);
        }

        _ffmpegOptions = ffmpegOptions.Value;
        _logger = logger;
    }

    /// <summary>
    /// 音频提取
    /// </summary>
    /// <param name="input"></param>
    /// <param name="output"></param>
    /// <param name="sampleRate"></param>
    /// <returns></returns>
    public async Task<bool> ExtractAudioAsync(string input,
        string output,
        int sampleRate = 16000,
        int channels = 1,
        string audioCodec = "pcm_s16le",
        TimeSpan? startTime = null,
        TimeSpan? duration = null)
    {
        try
        {
            var arguments = new List<string>
            {
                "-i", input,
                "-acodec", audioCodec,
                "-ar", sampleRate.ToString(),
                "-ac", channels.ToString()
            };

            // 可选：设置开始时间
            if (startTime.HasValue)
            {
                arguments.Add("-ss");
                arguments.Add(startTime.Value.ToString(@"hh\:mm\:ss"));
            }

            // 可选：设置持续时间
            if (duration.HasValue)
            {
                arguments.Add("-t");
                arguments.Add(duration.Value.ToString(@"hh\:mm\:ss"));
            }

            arguments.Add("-y"); // 覆盖输出文件
            arguments.Add(output);

            var result = await Cli.Wrap(_ffmpegOptions.FFmpegPath)
                .WithArguments(arguments)
                .WithValidation(CommandResultValidation.None)
                .ExecuteBufferedAsync()
                ;

            if (result.ExitCode == 0)
            {
                _logger.LogInformation($"音频提取成功: {output}");
                return true;
            }

            _logger.LogError($"音频提取失败: {result.StandardError}");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "音频提取失败");
        }

        return false;
    }
}